{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Title: #Print FooBar Alternately"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Difficulty: #Medium"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Category Title: #Concurrency"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tag Slug: #concurrency"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Name Translated: #多线程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solution Name: FooBar"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Title: #交替打印 FooBar"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Content:\n",
    "<p>给你一个类：</p>\n",
    "\n",
    "<pre>\n",
    "class FooBar {\n",
    "  public void foo() {\n",
    "&nbsp; &nbsp; for (int i = 0; i &lt; n; i++) {\n",
    "&nbsp; &nbsp; &nbsp; print(\"foo\");\n",
    "&nbsp;   }\n",
    "  }\n",
    "\n",
    "  public void bar() {\n",
    "&nbsp; &nbsp; for (int i = 0; i &lt; n; i++) {\n",
    "&nbsp; &nbsp; &nbsp; print(\"bar\");\n",
    "&nbsp; &nbsp; }\n",
    "  }\n",
    "}\n",
    "</pre>\n",
    "\n",
    "<p>两个不同的线程将会共用一个 <code>FooBar</code>&nbsp;实例：</p>\n",
    "\n",
    "<ul>\n",
    "\t<li>线程 A 将会调用&nbsp;<code>foo()</code>&nbsp;方法，而</li>\n",
    "\t<li>线程 B 将会调用&nbsp;<code>bar()</code>&nbsp;方法</li>\n",
    "</ul>\n",
    "\n",
    "<p>请设计修改程序，以确保 <code>\"foobar\"</code> 被输出 <code>n</code> 次。</p>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>示例 1：</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入：</strong>n = 1\n",
    "<strong>输出：</strong>\"foobar\"\n",
    "<strong>解释：</strong>这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法，\"foobar\" 将被输出一次。\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 2：</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入：</strong>n = 2\n",
    "<strong>输出：</strong>\"foobarfoobar\"\n",
    "<strong>解释：</strong>\"foobar\" 将被输出两次。\n",
    "</pre>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>提示：</strong></p>\n",
    "\n",
    "<ul>\n",
    "\t<li><code>1 &lt;= n &lt;= 1000</code></li>\n",
    "</ul>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Description: [print-foobar-alternately](https://leetcode.cn/problems/print-foobar-alternately/description/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solutions: [print-foobar-alternately](https://leetcode.cn/problems/print-foobar-alternately/solutions/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_cases = ['1', '2']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.condLock = threading.Condition()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "\n",
    "        with self.condLock:\n",
    "            for i in range(self.n):\n",
    "                \n",
    "                # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "                printFoo()\n",
    "                self.condLock.notify()\n",
    "                self.condLock.wait()\n",
    "            self.condLock.notify()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        with self.condLock:\n",
    "            for i in range(self.n):\n",
    "                \n",
    "                # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "                printBar()\n",
    "                self.condLock.notify()\n",
    "                self.condLock.wait()\n",
    "            self.condLock.notify()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.Lock_foo = Lock()\n",
    "        self.Lock_bar = Lock()\n",
    "        self.Lock_bar.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.Lock_foo.acquire()\n",
    "            printFoo()\n",
    "            self.Lock_bar.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.Lock_bar.acquire()\n",
    "            printBar()\n",
    "            self.Lock_foo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\n",
    "\n",
    "# 2023-09-14 21:01:44\n",
    "import threading\n",
    "\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.empty = threading.Semaphore(1)\n",
    "        self.full = threading.Semaphore(0)\n",
    "\n",
    "    def foo(self, printFoo: \"Callable[[], None]\") -> None:\n",
    "        for i in range(self.n):\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.empty.acquire()\n",
    "            printFoo()\n",
    "            self.full.release()\n",
    "\n",
    "    def bar(self, printBar: \"Callable[[], None]\") -> None:\n",
    "        for i in range(self.n):\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.full.acquire()\n",
    "            printBar()\n",
    "            self.empty.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self._tag = 0\n",
    "        self.n = n\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.wait_for(0)\n",
    "\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            \n",
    "            self.next()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.wait_for(1)\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            \n",
    "            self.next()\n",
    "    \n",
    "    def wait_for(self, n):\n",
    "        while self._tag != n:\n",
    "            continue\n",
    "\n",
    "    def next(self):\n",
    "        self._tag += 1\n",
    "        self._tag %= 2\n",
    "        time.sleep(1e-8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from time import sleep\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.waitFoo=True\n",
    "        self.waitBar=False\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            while self.waitBar:\n",
    "                sleep(0.00002)\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.waitBar=True\n",
    "            self.waitFoo=False\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            while self.waitFoo:\n",
    "                sleep(0.00002)\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.waitBar=False\n",
    "            self.waitFoo=True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foo_ = threading.Semaphore(1)\n",
    "        self.bar_ = threading.Semaphore(0)\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):        \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.foo_.acquire()\n",
    "            printFoo()\n",
    "            self.bar_.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.bar_.acquire()\n",
    "            printBar()\n",
    "            self.foo_.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foosm = Semaphore() # foo起始可打印次数1\n",
    "        self.barsm = Semaphore(0) # bar 起始可打印次数0\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.foosm.acquire() # foo打印次数-1\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.barsm.release() # bar打印次数+1\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.barsm.acquire() # bar打印次数-1\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.foosm.release() # foo打印次数+1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    t = \"bar\"\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            while self.t != \"bar\":\n",
    "                time.sleep(0.0001)\n",
    "            printFoo()\n",
    "            self.t = \"foo\"\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            while self.t != \"foo\":\n",
    "                time.sleep(0.0001)\n",
    "            printBar()\n",
    "            self.t = \"bar\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self,n):\n",
    "        self.n=n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.LockBar.release()        \n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            printBar()\n",
    "            self.LockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from time import sleep\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.waitFoo=True\n",
    "        self.waitBar=False\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            while self.waitBar:\n",
    "                sleep(0.0001)\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.waitBar=True\n",
    "            self.waitFoo=False\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            while self.waitFoo:\n",
    "                sleep(0.0001)\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.waitBar=False\n",
    "            self.waitFoo=True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.semaphore1 = threading.Semaphore(1)\n",
    "        self.semaphore2 = threading.Semaphore(0)\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "        \tself.semaphore1.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "        \tprintFoo()\n",
    "        \tself.semaphore2.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "        \tself.semaphore2.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "        \tprintBar()\n",
    "        \tself.semaphore1.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foocl = Lock()\n",
    "        self.barcl = Lock()\n",
    "        self.barcl.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.foocl.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.barcl.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.barcl.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.foocl.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foo_ = threading.Semaphore(1)\n",
    "        self.bar_ = threading.Semaphore(0)\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):        \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.foo_.acquire()\n",
    "            printFoo()\n",
    "            self.bar_.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.bar_.acquire()\n",
    "            printBar()\n",
    "            self.foo_.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foo_lock = Lock()\n",
    "        self.bar_lock = Lock()\n",
    "\n",
    "        self.bar_lock.acquire()\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "\n",
    "            self.foo_lock.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.bar_lock.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.bar_lock.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.foo_lock.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import queue\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.q = queue.Queue(1)\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.q.put(0)\n",
    "            printFoo()\n",
    "        \n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            self.q.get()\n",
    "            printBar()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import  Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.mutex_foo = Lock()\n",
    "        self.mutex_bar = Lock()          \n",
    "        self.mutex_bar.acquire()\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            self.mutex_foo.acquire()\n",
    "            printFoo()\n",
    "            self.mutex_bar.release()\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            self.mutex_bar.acquire()\n",
    "            printBar()\n",
    "            self.mutex_foo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from time import sleep\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.x = False\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            while self.x:\n",
    "                sleep(1e-4)\n",
    "            self.x = True\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            while not self.x:\n",
    "                sleep(1e-4)\n",
    "            self.x = False\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n \n",
    "        self.firstLock = threading.Lock()\n",
    "        self.secondLock = threading.Lock()\n",
    "        self.secondLock.acquire()\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "                self.firstLock.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "                printFoo()\n",
    "                self.secondLock.release()\n",
    " \n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "                self.secondLock.acquire()\n",
    "                # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "                printBar()\n",
    "                self.firstLock.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.fooLock = Lock()\n",
    "        self.barLock = Lock()\n",
    "        # 先给foo上锁，让foo先执行\n",
    "        self.fooLock.acquire()\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            # 给bar获得锁，但开始时不可用\n",
    "            self.barLock.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            # 这一步之后，bar的锁可以用了\n",
    "            self.fooLock.release()       \n",
    "\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.fooLock.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.barLock.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foo_lock = threading.Lock()\n",
    "        self.bar_lock = threading.Lock()\n",
    "        self.bar_lock.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.foo_lock.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.bar_lock.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.bar_lock.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.foo_lock.release()   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.la = Lock()\n",
    "        self.lb = Lock()\n",
    "        self.lb.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.la.acquire()\n",
    "            printFoo()\n",
    "            self.lb.release()\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.lb.acquire()\n",
    "            printBar()\n",
    "            self.la.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self,n):\n",
    "        self.n=n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.LockBar.release()        \n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            printBar()\n",
    "            self.LockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Condition\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.condition = Condition()\n",
    "        self.current = 'foo'\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            with self.condition:\n",
    "                while self.current != 'foo':\n",
    "                    self.condition.wait()\n",
    "                printFoo()\n",
    "                self.current = 'bar'\n",
    "                self.condition.notify_all()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            with self.condition:\n",
    "                while self.current != 'bar':\n",
    "                    self.condition.wait()\n",
    "                printBar()\n",
    "                self.current = 'foo'\n",
    "                self.condition.notify_all()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock, Condition\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.condition = Condition()\n",
    "        self.foo_turn = True\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            with self.condition:\n",
    "                while not self.foo_turn:\n",
    "                    self.condition.wait()\n",
    "                # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "                printFoo()\n",
    "                self.foo_turn = False\n",
    "                self.condition.notify()\n",
    "        \n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            with self.condition:\n",
    "                while self.foo_turn:\n",
    "                    self.condition.wait()\n",
    "                # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "                printBar()\n",
    "                self.foo_turn = True\n",
    "                self.condition.notify()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.event = threading.Event()\n",
    "        self._tag = 0\n",
    "        self.n = n\n",
    "        self.event.set()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            while self._tag != 0:\n",
    "                if not self.event.is_set():\n",
    "                    self.event.wait()\n",
    "                self.event.clear()\n",
    "                \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            \n",
    "            self._tag += 1\n",
    "            self._tag %= 2\n",
    "            self.event.set()\n",
    "\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            while self._tag != 1:\n",
    "                if not self.event.is_set():\n",
    "                    self.event.wait()\n",
    "                self.event.clear()\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            \n",
    "            self._tag += 1\n",
    "            self._tag %= 2\n",
    "            self.event.set()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.fooLock = Lock()\n",
    "        self.barLock = Lock()\n",
    "        self.barLock.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):     \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.fooLock.acquire()\n",
    "            printFoo()\n",
    "            self.barLock.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.barLock.acquire()\n",
    "            printBar()\n",
    "            self.fooLock.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore\n",
    "\n",
    "\n",
    "class FooBar:\n",
    "    __slots__ = (\"n\", \"foo_available\", \"bar_available\")\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foo_available = Semaphore(1)\n",
    "        self.bar_available = Semaphore(0)\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "\n",
    "        for i in range(self.n):\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.foo_available.acquire()\n",
    "            printFoo()\n",
    "            self.bar_available.release()\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "\n",
    "        for i in range(self.n):\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.bar_available.acquire()\n",
    "            printBar()\n",
    "            self.foo_available.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.event = threading.Event()\n",
    "        self._tag = 0\n",
    "        self.n = n\n",
    "        self.event.set()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.wait_for(0)\n",
    "\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            \n",
    "            self.next()\n",
    "\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.wait_for(1)\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            \n",
    "            self.next()\n",
    "    \n",
    "    def wait_for(self, n):\n",
    "        while self._tag != n:\n",
    "            if not self.event.is_set():\n",
    "                self.event.wait()\n",
    "            self.event.clear()\n",
    "\n",
    "\n",
    "    def next(self):\n",
    "        self._tag += 1\n",
    "        self._tag %= 2\n",
    "        self.event.set()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.lockfoo = threading.Lock()\n",
    "        self.lockbar = threading.Lock()\n",
    "        self.lockfoo.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "\n",
    "        for i in range(self.n):\n",
    "            self.lockbar.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.lockfoo.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.lockfoo.acquire()\n",
    "            printBar()\n",
    "            self.lockbar.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    t = \"bar\"\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            while self.t != \"bar\":\n",
    "                time.sleep(0.00001)\n",
    "            printFoo()\n",
    "            self.t = \"foo\"\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            while self.t != \"foo\":\n",
    "                time.sleep(0.00001)\n",
    "            printBar()\n",
    "            self.t = \"bar\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self,n):\n",
    "        self.n=n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.LockBar.release()        \n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            printBar()\n",
    "            self.LockFoo.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from time import sleep\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.waitFoo=True\n",
    "        self.waitBar=False\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            while self.waitBar:\n",
    "                sleep(0.001)\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.waitBar=True\n",
    "            self.waitFoo=False\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            while self.waitFoo:\n",
    "                sleep(0.001)\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.waitBar=False\n",
    "            self.waitFoo=True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading \n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.s1=threading.Semaphore(1)\n",
    "        self.s2=threading.Semaphore(0)\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.s1.acquire()\n",
    "            printFoo()\n",
    "            self.s2.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.s2.acquire()\n",
    "            printBar()\n",
    "            self.s1.release()\n",
    "\n",
    "# 作者：p瓜皮\n",
    "# 链接：https://leetcode.cn/problems/print-foobar-alternately/solutions/79145/python3-xin-hao-liang-pvcao-zuo-by-xjcai/\n",
    "# 来源：力扣（LeetCode）\n",
    "# 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "import time\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.event0, self.event1 = threading.Event(), threading.Event()\n",
    "        self.event0.set()\n",
    "\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            self.event0.wait()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.event0.clear()\n",
    "            self.event1.set()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            self.event1.wait()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.event1.clear()\n",
    "            self.event0.set()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.sem1=threading.Semaphore(1)\n",
    "        self.sem2=threading.Semaphore(0)\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.sem1.acquire()\n",
    "            printFoo()\n",
    "            self.sem2.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.sem2.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.sem1.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import queue\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.q1 = queue.Queue(1)\n",
    "        self.q2 = queue.Queue(1)\n",
    "        self.q2.put(0)\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.q2.get()\n",
    "            printFoo()\n",
    "            self.q1.put(0)\n",
    "        \n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            self.q1.get()\n",
    "            printBar()\n",
    "            self.q2.put(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.lockFoo = Lock()\n",
    "        self.lockBar = Lock()\n",
    "        self.lockBar.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None: \n",
    "        for i in range(self.n):\n",
    "            self.lockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.lockBar.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.lockBar.acquire()\n",
    "            printBar()\n",
    "            self.lockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    t = \"bar\"\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            while self.t != \"bar\":\n",
    "                time.sleep(0.00001)\n",
    "            printFoo()\n",
    "            self.t = \"foo\"\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            while self.t != \"foo\":\n",
    "                time.sleep(0.00001)\n",
    "            printBar()\n",
    "            self.t = \"bar\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.condLock = threading.Condition()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "\n",
    "        with self.condLock:\n",
    "            for i in range(self.n):\n",
    "                \n",
    "                # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "                printFoo()\n",
    "                self.condLock.notify()\n",
    "                self.condLock.wait()\n",
    "            self.condLock.notify()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        with self.condLock:\n",
    "            for i in range(self.n):\n",
    "                \n",
    "                # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "                printBar()\n",
    "                self.condLock.notify()\n",
    "                self.condLock.wait()\n",
    "            self.condLock.notify()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.Foolock=Lock()\n",
    "        self.Barlock=Lock()\n",
    "        self.Barlock.acquire()\n",
    "\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):            \n",
    "            self.Foolock.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.Barlock.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            self.Barlock.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.Foolock.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.lock_foo = threading.Lock()\n",
    "        self.lock_bar = threading.Lock()\n",
    "        self.lock_bar.acquire()\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.lock_foo.acquire()\n",
    "            printFoo()\n",
    "            self.lock_bar.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.lock_bar.acquire()\n",
    "            printBar()\n",
    "            self.lock_foo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "    import time\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.LockBar.release()\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            printBar()\n",
    "            self.LockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foolock = threading.Lock()\n",
    "        self.barlock = threading.Lock()\n",
    "        self.barlock.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.foolock.acquire()\n",
    "            printFoo()\n",
    "            self.barlock.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.barlock.acquire()\n",
    "            printBar()\n",
    "            self.foolock.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self._tag = 0\n",
    "        self.n = n\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.wait_for(0)\n",
    "\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            \n",
    "            self.next()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.wait_for(1)\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            \n",
    "            self.next()\n",
    "    \n",
    "    def wait_for(self, n):\n",
    "        while self._tag != n:\n",
    "            continue\n",
    "\n",
    "    def next(self):\n",
    "        self._tag = (self._tag + 1) % 2\n",
    "        time.sleep(1e-8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.LockBar.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.LockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self,n):\n",
    "        self.n=n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.LockBar.release()        \n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            printBar()\n",
    "            self.LockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.lock_foo = threading.Lock()\n",
    "        self.lock_bar = threading.Lock()\n",
    "        self.lock_bar.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.lock_foo.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.lock_bar.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.lock_bar.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.lock_foo.release()\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foo_ = threading.Semaphore(1)\n",
    "        self.bar_ = threading.Semaphore(0)\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):        \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.foo_.acquire()\n",
    "            printFoo()\n",
    "            self.bar_.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.bar_.acquire()\n",
    "            printBar()\n",
    "            self.foo_.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line. \n",
    "            printFoo()\n",
    "            self.LockBar.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.LockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading  \n",
    "  \n",
    "class FooBar:  \n",
    "    def __init__(self, n):  \n",
    "        self.n = n  \n",
    "        self.foo_sem = threading.Semaphore(0)  # Semaphore initialized correctly  \n",
    "        self.bar_sem = threading.Semaphore(0)\n",
    "  \n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:  \n",
    "        for i in range(self.n):\n",
    "            if i != 0:\n",
    "                self.bar_sem.acquire()  # Wait until a slot is available for bar\n",
    "            printFoo()\n",
    "            self.foo_sem.release()  # Release the slot for foo  \n",
    "  \n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:  \n",
    "        for i in range(self.n):  \n",
    "            self.foo_sem.acquire()  # Wait until a slot is available for foo  \n",
    "            printBar()  \n",
    "            self.bar_sem.release()  # Release the slot for bar  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.s1 = threading.Semaphore(1)\n",
    "        self.s2 = threading.Semaphore(0)\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.s1.acquire()\n",
    "            printFoo()\n",
    "            self.s2.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.s2.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.s1.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.LockBar.release()\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            printBar()\n",
    "            self.LockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.LockBar.release()   \n",
    "\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            printBar()\n",
    "            self.LockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "\n",
    "# 没看懂\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.LockBar.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.LockFoo.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Lock\n",
    "\n",
    "class FooBar:\n",
    "    def __init__(self,n):\n",
    "        self.n=n\n",
    "        self.LockFoo = Lock()\n",
    "        self.LockBar = Lock()\n",
    "        self.LockBar.acquire()\n",
    "\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockFoo.acquire()\n",
    "            printFoo()\n",
    "            self.LockBar.release()        \n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            self.LockBar.acquire()\n",
    "            printBar()\n",
    "            self.LockFoo.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.foo_lock = threading.Lock()\n",
    "        self.bar_lock = threading.Lock()\n",
    "        self.bar_lock.acquire()  # step1\n",
    "        \n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            self.foo_lock.acquire()    # step2 \\ step6\n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            printFoo()\n",
    "            self.bar_lock.release()  #step3\n",
    "            \n",
    "\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        for i in range(self.n):\n",
    "            self.bar_lock.acquire() #step4\n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            printBar()\n",
    "            self.foo_lock.release()  #step5\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading \n",
    "class FooBar:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.s1=threading.Semaphore(1)\n",
    "        self.s2=threading.Semaphore(0)\n",
    "\n",
    "\n",
    "    def foo(self, printFoo: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printFoo() outputs \"foo\". Do not change or remove this line.\n",
    "            self.s1.acquire()\n",
    "            printFoo()\n",
    "            self.s2.release()\n",
    "\n",
    "\n",
    "    def bar(self, printBar: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        for i in range(self.n):\n",
    "            \n",
    "            # printBar() outputs \"bar\". Do not change or remove this line.\n",
    "            self.s2.acquire()\n",
    "            printBar()\n",
    "            self.s1.release()\n",
    "\n",
    "# 作者：p瓜皮\n",
    "# 链接：https://leetcode.cn/problems/print-foobar-alternately/solutions/79145/python3-xin-hao-liang-pvcao-zuo-by-xjcai/\n",
    "# 来源：力扣（LeetCode）\n",
    "# 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
